======================================================================== = Systemprogrammierung in PCQ-Pascal = = Kurs für AmigaGadget/Purity - Teil III = ======================================================================== Bisherige Kursteile : Teil I : Voraussetzungen,Screens,Windows Teil II : Einfache Grafikausgabe Was für ein Tag ! Stoltenberg ist zurückgetreten und ich muß jetzt noch schnell Teil drei dieses Kurses fertigstellen.... Schwitz. Also gut, wie versprochen : noch einige Grafikbefehle : im Include-File "Graphics/Text.i" finden sich unter anderem : GText (window^.RPort,string,count) - Gibt einen Text, der in der Variable string gespeichert ist count Zeichen lang aus. Normalerweise setzt man count:= StrLen (string); TextLength (window^.RPort,string,count) - Gibt die Anzahl der Pixel an, die von count Zeichen des Strings string benötigt werden würden. Normalerweise Zeichen*8, aber seit Kick2.0 sollte man da vorsichtig sein... In den Includes "Graphics/Pens.i" und "Graphics/RastPort.i" erschließt sich uns eine neue Dimension der Grafikausgabe : gefüllte Flächen. Damit man diese darstellen kann, muß man vorerst eine sogenannte TmpRas-Struktur einrichten und dem Rastport einverleiben. Dies geschieht mit : InitTmpRas (TmpRasPtr , Buffer , Buffersize) - Initialisiert eine solche Struktur. Wie sieht das Teil nun aus ? TmpRas = record RasPtr : Address; Size : Integer; end; Yo, was wollen uns diese Variablen sagen ? Nun, RasPtr wird von InitTmpRas besetzt und Size können wird mit der im File "Graphics/Gfx.i" besetzt. Also : Size:=RASSIZE (Breite,Hoehe); Buffer ist ein Zeiger auf ein vorher zu belegendes Raster. Dieses wird mit Buffer:=AllocRaster (Breite,Hoehe) belegt. Buffersize letztendlich kann wieder mit RASSIZE berechnet werden : Buffersize:=RASSIZE (Breite,Hoehe). Normalerweise verwendet man für Breite und Hoehe die entsprechenden Ausmaße des Fensters. Das ganze wird dann in die Windowstruktur eingebunden : window^.RPort^.TmpRas:=TmpRasPtr; Flood (window^.RPort,mode,x,y) - füllt eine zusammenhänge Fläche, in der der Punkt P (x/y) enthalten ist. Mode wird in der Regel 1 sein, Mode 0 benötigt eine Umrandungslinie mit dem AOlPen und ist an sich unnötig.... Es gibt noch einige andere Flächenformen, die zwar einfacher zu hand- haben sind, die aber noch einiges weiteres an Strukturkram benötigen. Deshalb : heute nicht ! Ein anderes Mal mehr dazu. Nun wollen wir uns zwei Procedure schreiben, die uns die Arbeit verkürzen. Nämlich in etwa so : PROCEDURE Print (rp : Address; xs , ys : Short; stext : String); BEGIN Move (rp,xs,ys); GText (rp,stext,StrLen(stext)); END; und PROCEDURE InitialisiereRaster (itmpras : TmpRasPtr; VAR ARaster : Address; width , height : Short ; swindow : WindowPtr); BEGIN ARaster:=AllocRaster(width,height); WITH itmpras^ DO BEGIN RasPtr := NIL; Size := RASSIZE (width,height); END; InitTmpRas (itmpras , ARaster , RASSIZE (width,height)); swindow^.RPort^.TmpRas := itmpras; END; Und nicht vergessen : Wenn man das Programm beendet, dann sollte man das belegte Raster mit FreeRaster (Buffer,Breite,Hoehe); wieder freigeben. Machen wir halt mal ein kloines Beispiel : Program KursProgramm; { Listing für den AMIGAGadget/Purity - Pascalkurs , } { Dritte Schritte in der Grafikprogrammierung } {$I "Include:Intuition/Intuition.I" } {$I "Include:Exec/Libraries.I" } {$I "Include:Graphics/Graphics.I" } {$I "Include:Libraries/Dos.I" } {$I "Include:Graphics/Pens.I" } {$I "Include:Graphics/Rastport.I" } {$I "Include:Utils/Stringlib.I" } VAR myscreen : ScreenPtr; mywindow : WindowPtr; PROCEDURE Line (rp : Address ; xs , ys , xe , ye : Short); BEGIN Move (rp , xs , ys); Draw (rp , xe , ye); END; PROCEDURE Box (rp : Address ; xs , ys , xe , ye : Short); BEGIN Line (rp,xs,ys,xe,ys); Line (rp,xe,ys,xe,ye); Line (rp,xe,ye,xs,ye); Line (rp,xs,ye,xs,ys); END; PROCEDURE Print (rp : Address; xs , ys : Short; stext : String); BEGIN Move (rp,xs,ys); GText (rp,stext,StrLen(stext)); END; PROCEDURE InitialisiereRaster (itmpras : TmpRasPtr; VAR ARaster : Address; width , height : Short ; swindow : WindowPtr); BEGIN ARaster:=AllocRaster(width,height); WITH itmpras^ DO BEGIN RasPtr := NIL; Size := RASSIZE (width,height); END; InitTmpRas (itmpras , ARaster , RASSIZE (width,height)); swindow^.RPort^.TmpRas := itmpras; END; PROCEDURE CloseDisplay; VAR i : Integer; { Sollte ein Teil des Displays offen sein, dann wird er von } { dieser Routine geschlossen. } BEGIN IF mywindow<>NIL THEN CloseWindow (mywindow); IF myscreen<>NIL THEN CloseScreen (myscreen); IF GfxBase<>NIL THEN CloseLibrary (GfxBase); END; PROCEDURE BreakProgram (reason : STRING); { Diese Routine schließt alles bisher geöffnete, druckt den } { Fehlergrund aus und bricht dann das Programm ab. } BEGIN CloseDisplay; WRITELN ('Program error : ',reason); Exit (42); END; PROCEDURE OpenLibs; CONST GraphicName : String = "graphics.library"; BEGIN GfxBase:=OpenLibrary (GraphicName,0); END; PROCEDURE OpenDisplay; { Diese Routine erstellt ein Display. } CONST mynewscreen : NewScreen = (0,0,640,256,2,0,1,HIRES, CUSTOMSCREEN_f,NIL, NIL,NIL,NIL); NewWin : NewWindow = (100,50,320,128,0,1,0, SMART_REFRESH+WINDOWDRAG+ ACTIVATE+SMART_REFRESH,NIL,NIL, "Unsere neuen schicken Befehle !", NIL,NIL,0,0,0,0,CUSTOMSCREEN_f); BEGIN myscreen := OpenScreen (Adr(mynewscreen)); IF myscreen=NIL THEN BreakProgram ("Couldn't open Screen"); NewWin.Screen:=myscreen; mywindow := OpenWindow (Adr(NewWin)); IF mywindow=NIL THEN BreakProgram ("Couldn't open Window"); END; PROCEDURE NeueBefehle; {Demonstration der neuen Befehle. } VAR MyTmpRas : TmpRas; MyRaster : Address; BEGIN {Ganz am Anfang eine kleine Textausgabe } SetAPen (mywindow^.RPort,1); Print (mywindow^.RPort,10,20,"Hello World ! Let's have some"); Print (mywindow^.RPort,10,28,"NEW GRAPHIC FUNCTIONS !!!"); {Zuersteinmal Initialisierung der benötigten Strukturen. } InitialisiereRaster (Adr(MyTmpRas),MyRaster,mywindow^.Width, mywindow^.Height,mywindow); {Und dann einen Kreis, der von uns gefüllt wird ! } DrawCircle (mywindow^.RPort,60,70,20); Flood (mywindow^.RPort,1,60,70); {Auch noch ein gefülltes Dreieck.... } Line (mywindow^.RPort,110,60,180,85); Line (mywindow^.RPort,180,85,100,70); Line (mywindow^.RPort,100,70,110,60); Flood (mywindow^.RPort,1,120,65); {Und wieder ein wenig Text } SetAPen (mywindow^.RPort,3); Print (mywindow^.RPort,10,110,"Das war's. See U later."); FreeRaster (MyRaster,mywindow^.Width,mywindow^.Height); END; PROCEDURE WarteEinWenig; BEGIN Delay (1000); END; BEGIN OpenLibs; OpenDisplay; NeueBefehle; WarteEinWenig; CloseDisplay; END. Es gäbe noch sehr viel über Grafik und ihre Anwendung zu erzählen, doch finde ich es wichtiger, die Brücke zum Anwender zu schlagen, will sagen, im nächsten Teil mit dem Kapitel Messages zu beginnen. (Klingt geheimnisvoll, oder ?) Wer Kritik oder Lob für diesen Kurs, Verbesserungsvorschläge oder Fragen (es gibt keine dummen Fragen !!) hat, melde sich entweder bei mir Andreas Neumann ; Auf dem Ruhbühl 151 ; 7997 Immenstaad oder in der Purity. Bye. © 1992 by Andreas Neumann für AmigaGadget von Nils Kassube und Purity von Steppenbrand und Diesel